iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 3
0
自我挑戰組

玩轉 React 從0到1系列 第 7

【Day 7】關於ES6 模組系統

  • 分享至 

  • xImage
  •  

前言

當程式碼越寫越多的時候,尤其是要去開發大型專案,我們需要有組織的去管理程式碼,那看過前面文章的朋友應該知道,像是物件或是原型都沒有公開私有的概念,或許可以針對屬性集中管理,但是卻無法排除污染作用域的問題;此外,也因為沒有模組的概念,JS 無法將一個大專案拆分成許多互相依賴的小專案再將它組合起來(其他語言像是 python 都有 import 的功能)。

什麼是模組化 ?

隔絕其他的文件,僅引用當前模組所需要的其他模組或是模組方法,就是模組化。

在 ES6 之前,有幾種常用的模組概念,我們先來介紹一下:

CommonJS

最早採用 CommonJS 標準之一的就是 Node.js,它有 4 個重要的變量支持著模組化這個概念,分別是 module,export, require, global。使用的時候,用 module.exports輸出模組,需要的時候用 require 引入模組。CommonJS是用同步的方式加載模組,所以有時候速度會超慢....(阻塞)。

// 定義模組 calculate.js
var initial = 0;
function getSquareArea(width){
    return Math.pow(width, 2);
}
module.exports = {
    calculateArea: calculateArea,
    initial : initial
}

// 引用自定義模組
var calculate = require('./calculate');
calculate.getSquareArea(5);    // 25

// 引用核心模組
var http = require('http');
http.createService(...).listen(8888);

AMD

可以說是專門為瀏覽器中的 JS 環境設計的規範,最著名的就是 require.js,它是以異步的方式去加載模組,也比較符合瀏覽器的加載方式,但是最大的問題是一開始就會把所有相關的模組載入進來,不能按照需求加載。

// require([module],callback);  
// example
require(['timer.js'],function(clock){
  timer.start();
})

CMD

規範跟 AMD 很相像,主要差異在執行引用這件事時間點不一樣,開發者可以在需要用到模組實在 require,但是對於 JS 編輯器來說,需要先解析一遍才知道引用了哪些模組,雖然解析時間很短但卻會影響到性能。常見的套件像是 sea.js。

define(function(require,exports,module){
  var timer = require('timer.js');
  timer.start();
})

ES6 模組

  • ES6 模組有各自的作用域,而且內部自動定義為 use strict (嚴格模式)
  • ES6 分隔的原則是一個檔案一個模組
  • ES6 使用 export 輸出, import 匯入

嚴格模式注意事項

  • 變量需要先宣告
  • 物件內有重複屬性
  • 不可以用保留字當作名稱,像是 static、interface、protected
  • arguments、eval 不能作為變數名稱
  • this 不可指向全域
  • 不可以刪除變量,只能刪除屬性

Import / Export

可以將函式、物件甚至或是純值匯出,可區分為:

Named Export(具名匯出)

需要先將輸出值、表達式、函式、類別先賦予名稱才能匯出,import 也需要用所賦予的名稱才能引用

// export file
export const id = 1

export function getUserDetail(id, name, address) {
  return `UserId: ${id}, Name: ${name}, Address: ${address}`
}

// import file
// 這裏的 as 是 重新命名
import { getUserDetail as renameGetUserDetail } from './module.js'

Default Export(預設匯出)

當輸出只有一個輸出值、表達式、函式、類別時,做為最低使用情況預設輸出時會加入default,一個檔案只能有一個

// 注意:一份檔案只會有一個 default export,這裡只是為了方便均寫在此
// export object file
export default {
  id: 1,
  name: 'Jacky',
  method: function() {
    console.log('call method');
  },
}

// export function file
export default function() {
  console.log('這是一段函式');
}

// export class file
export default class {
  constructor(name) {
    this.id = id;
  }
  getId() {
    console.log(this.id);
  }
}

// import object file
import object as defaultNamed from './module.js'
console.log(object.name) // Jacky

ES6 模組 對比 CommonJS

CommonJS 模組輸出的是值的緩存,沒有所謂的動態更新;而 ES6 的 export 輸出的是值的引用,所以會動態更新(例如在 call function 之後)

CommonJS

// module.js 
let id = 1;
function changeId() {
  id = 2;
}
module.exports = {
  get id(){
    return id
  },
  changeId: changeId,
};

//main.js
var main = require('./module.js')
console.log(main.id); // 1
main.changeId();
console.log(main.id); // 1

ES6

// module.js 
export let id = 1;
export function changeId() {
  id = 2;
}

//main.js
import {id,changeId} from './module.js'
console.log(id); // 1
changeId();
console.log(id); // 2

結論

  • 介紹了 模組化
  • 介紹了 CommonJS, AMD, CMD
  • 介紹了 ES6 模組 (包含 Import, Export)
  • 介紹了 CommonJS vs ES6模組
    /images/emoticon/emoticon30.gif

上一篇
【Day 6】關於ES6作用域
下一篇
【Day 8】關於ES6 關鍵字 this
系列文
玩轉 React 從0到130
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言